#include "Game.h"

#include <time.h>
#include <sstream>

Game::Game()
{
	init();

}

void Game::loadStars()
{
	starPointTex.loadFromFile("art/star_point.png");
	for(int i = 0; i < 128; ++i)
	{
		starSpritesLayer1[i].setTexture(starPointTex);
		starSpritesLayer2[i].setTexture(starPointTex);
		starSpritesLayer3[i].setTexture(starPointTex);
		float randomAlpha = rand() % 255;
		starSpritesLayer1[i].setColor(sf::Color(255, 255, 255, randomAlpha));
		starSpritesLayer2[i].setColor(sf::Color(255, 255, 255, randomAlpha));
		starSpritesLayer3[i].setColor(sf::Color(255, 255, 255, randomAlpha));
		float randomX = rand() % 1024;
		float randomY = rand() % 768;
		starSpritesLayer1[i].setPosition(randomX,randomY);
		starSpritesLayer2[i].setPosition(randomX,randomY);
		starSpritesLayer3[i].setPosition(randomX,randomY);
	}

}

void Game::init()
{
	r = new Room("rooms/tutorial_room.txt");
	level = 0;
	trueLevel = 0;
	shaking = false;
	x_offset = 10;
	y_offset = 0;
	PDALightCounter = 0;

	beatDirection = 0.05;
	heartBeat = 1400.0f;
	heartClock.restart();

	explanationOpen = false;

	// Load the font from a file
	courier.loadFromFile("art/Courier_New.ttf");

	score = 0;
	scoreCalculated = false;
	fadedIn = false;

	scoreString = "Score: ";

	scoreText.setFont(courier);
	scoreText.setCharacterSize(100);
	scoreText.setStyle(sf::Text::Bold);
	scoreText.setColor(sf::Color(255, 255, 255, 0));

	act.switchLightsOn();
	r->setTutorial(true);
	tutorialOn = true;

	introBackTex.loadFromFile("art/title_back.png");
	introBackSprite.setTexture(introBackTex);
	introBackSprite.setColor(sf::Color(255, 255, 255, 255));
	introBackSprite.setPosition(0,0);

	introFrontTex.loadFromFile("art/title_front.png");
	introFrontSprite.setTexture(introFrontTex);
	introFrontSprite.setColor(sf::Color(255, 255, 255, 255));
	introFrontSprite.setPosition(0,-100);

	explanationText.loadFromFile("art/story_screen_text.png");
	explanationSprite.setTexture(explanationText);
	explanationSprite.setColor(sf::Color(255, 255, 255, 255));
	explanationSprite.setPosition(0, 40);
	
	heartTexture.loadFromFile("art/heart.png");
	heartSprite.setTexture(heartTexture);
	heartSprite.setColor(sf::Color(255, 255, 255, 255));
	heartSprite.setPosition(512 - (heartSprite.getGlobalBounds().width / 2), 400 - (heartSprite.getGlobalBounds().height / 2));

	srand(time(NULL));

	isIntro = true;
	loadStars();

	black_tex.loadFromFile("art/black_back.png");
	blackBack.setTexture(black_tex);
	blackBack.setColor(sf::Color(255, 255, 255, 255));
	blackBack.setPosition(0, 0);


	shipSidesTex.loadFromFile("art/sides_with_stars.png");
	shipSides.setTexture(shipSidesTex);
	shipSides.setColor(sf::Color(255, 255, 255, 255));
	shipSides.setPosition(0, 0);
	fadeTex.loadFromFile("art/fade_back.png");
	fadeSprite.setTexture(fadeTex);
	fadeSprite.setColor(sf::Color(255, 255, 255, 0));
	fadeSprite.setPosition(0, 0);

	introTitleText.loadFromFile("art/title_banner.png");
	introTitleSprite.setTexture(introTitleText);
	introTitleSprite.setColor(sf::Color(255, 255, 255, 0));
	introTitleSprite.setPosition(0, 0);

	PDALightTexture.loadFromFile("art/PDA_light_texture.png");
	PDALightSprite.setTexture(PDALightTexture);
	PDALightSprite.setColor(sf::Color(255, 255, 255, 225));
	PDALightSprite.setPosition(*r->getPDALightPos());

	fadeInComplete = false;
	fadeOutComplete = false;
	fading = false;
	explosion = new Explosion();


	screamBuffer.loadFromFile("Sound/scream.wav");
	screamSound.setBuffer(screamBuffer);
	screamSound.setVolume(80);

	deathRoom = false;
	loop = 0;

	redTex.loadFromFile("art/red.png");
	redSprite.setTexture(redTex);
	redSprite.setColor(sf::Color(255,255,255,255));
	redSprite.setPosition(128,0);

	introTune.openFromFile("Sound/DarknessComing.wav");
	introTune.setLoop(true);
	introTune.play();
}

void Game::update()
{
	r->update(isIntro);

	if(!isIntro){

		if (r->getKillPlayer() && !deathRoom)
		{
			screamSound.play();
			deathRoom = true;
			delete r;
			r = new Room("rooms/death_room.txt");
			r->setTutorial(false);
			r->getBadGuy()->killPlayer = true;
			//show the baddie
		}


		if(deathRoom && screamSound.getStatus() == sf::SoundSource::Stopped){

			if(!fading)
			{
				fadeSprite.setColor(sf::Color(255,255,255,0));
			}
			finalFade();
		}

		if((r->getComplete() && fadeOutComplete))
		{
			//Play door open sound
			score += (r->getBadGuy()->getDeathCutOff() - r->getBadGuy()->getCurrentPitch()) * 1000;

			act.switchLightsOff();
			level++;
			trueLevel++;
			delete r;

			if(level > 9)
			{
				level = 1;
			}

			std::string roomDir = "rooms/room";
			char c = level + 48;

			roomDir.push_back(c);

			roomDir += ".txt";

			r = new Room(roomDir);
			PDALightSprite.setPosition(*r->getPDALightPos());
			act.resetPosition();
			r->setTutorial(false);
		}
		else if(r->getComplete() && !fadeOutComplete )
		{
			fadeOut();

		}
		if(fadeOutComplete && !fadeInComplete)
		{
			fadeIn();
		}

		if(fadeInComplete && fadeOutComplete)
		{
			fadeInComplete = false;
			fadeOutComplete = false;
			fading = false;
		}

		if(!deathRoom){
			explosion->update();
			act.update(r);
		}


		r->getBadGuy()->setIncreaseRates(trueLevel);
		act.update(r);

		for(int i = 0; i < 128; ++i)
		{
			if(i < 63)
			{
				std::uniform_int_distribution<int> distribution(0, 87);

				if(starSpritesLayer2[i].getPosition().y > 768)
				{
					float randomX = distribution(generator);
					starSpritesLayer2[i].setPosition(randomX, 0);
				}
				if(starSpritesLayer3[i].getPosition().y > 768)
				{
					float randomX = distribution(generator);
					starSpritesLayer3[i].setPosition(randomX, 0);
				}
			}
			else
			{
				std::uniform_int_distribution<int> distribution(937, 1024);

				if(starSpritesLayer2[i].getPosition().y > 768)
				{
					float randomX = distribution(generator);
					starSpritesLayer2[i].setPosition(randomX, 0);
				}
				if(starSpritesLayer3[i].getPosition().y > 768)
				{
					float randomX = distribution(generator); 
					starSpritesLayer3[i].setPosition(randomX, 0);
				}
			}

			starSpritesLayer2[i].move(0.0f, 1.0f);
			starSpritesLayer3[i].move(0.0f, 5.0f);
		}

		

	}else{

		currentTime = heartClock.getElapsedTime().asMilliseconds();

		if(currentTime >= heartBeat)
		{
			heartSprite.scale(1 + beatDirection, 1 + (beatDirection*2));
			beatDirection = -beatDirection;
			heartClock.restart();
		}
		else if(currentTime >= heartBeat / 2)
		{
			heartSprite.scale(1 + beatDirection, 1 + (beatDirection*2));
			beatDirection = -beatDirection;
			heartClock.restart();
		}

		//Intro
		if(introTitleSprite.getColor().a < 253)
		{
			counter++;
			if(counter % 3 == 0)
			{
				introTitleSprite.setColor(sf::Color(255, 255, 255, (introTitleSprite.getColor().a + 1 )));
			}
		}

		for(int i = 0; i < 128; ++i)
		{
			if(starSpritesLayer2[i].getPosition().x < 0)
			{
				float randomY = rand() % 768;
				starSpritesLayer2[i].setPosition(1024, randomY);
			}
			if(starSpritesLayer3[i].getPosition().x < 0)
			{
				float randomY = rand() % 768;
				starSpritesLayer3[i].setPosition(1024, randomY);
			}
			starSpritesLayer2[i].move(-1.0f, 0.0f);
			starSpritesLayer3[i].move(-3.0f, 0.0f);
		}

		if(sf::Joystick::isButtonPressed(0,1))
		{
			introTune.stop();

			explanationOpen = true;

			/*for(int i = 0; i < 128; ++i)
			{
				if(i < 63)
				{
					std::uniform_int_distribution<int> distribution(0, 87);
					std::uniform_int_distribution<int> ydistribution(0, 768);
					float randomX = distribution(generator);
					float randomY = ydistribution(generator);
					starSpritesLayer2[i].setPosition(randomX, randomY);

					randomX = distribution(generator);
					randomY = ydistribution(generator);
					starSpritesLayer3[i].setPosition(randomX, randomY);

				}
				else
				{
					std::uniform_int_distribution<int> distribution(937, 1024);
					std::uniform_int_distribution<int> ydistribution(0, 768);
					float randomX = distribution(generator);
					float randomY = ydistribution(generator);
					starSpritesLayer2[i].setPosition(randomX, randomY);

					randomX = distribution(generator);
					randomY = ydistribution(generator);
					starSpritesLayer3[i].setPosition(randomX, randomY);
				}
			}*/
		}
		else if(sf::Joystick::isButtonPressed(0, 0))
		{
			if(explanationOpen)
			{
				explanationOpen = false;
				isIntro = false;
			}
			else
			{
				introTune.stop();
				act.switchLightsOff();
				tutorialOn = false;
				isIntro = false;
				r = new Room("rooms/room1.txt");
				r->setTutorial(false);
				for(int i = 0; i < 128; ++i)
				{
					if(i < 63)
					{
						std::uniform_int_distribution<int> distribution(0, 87);
						std::uniform_int_distribution<int> ydistribution(0, 768);
						float randomX = distribution(generator);
						float randomY = ydistribution(generator);
						starSpritesLayer2[i].setPosition(randomX, randomY);

						randomX = distribution(generator);
						randomY = ydistribution(generator);
						starSpritesLayer3[i].setPosition(randomX, randomY);

					}
					else
					{
						std::uniform_int_distribution<int> distribution(937, 1024);
						std::uniform_int_distribution<int> ydistribution(0, 768);
						float randomX = distribution(generator);
						float randomY = ydistribution(generator);
						starSpritesLayer2[i].setPosition(randomX, randomY);

						randomX = distribution(generator);
						randomY = ydistribution(generator);
						starSpritesLayer3[i].setPosition(randomX, randomY);
					}
				}
			}
		}

	}
}

void Game::handleEvent(sf::Event e)
{
	if(e.type == sf::Event::JoystickButtonPressed && e.joystickButton.button == 5){
		r->setComplete();
	}
}

void Game::render(sf::RenderWindow *w)
{
	// Clear the screen (fill it with black color)
	w->clear();

	// Render objects

	if(!isIntro){

		if(explosion->exploding)
		{
			x_offset *= -0.99;
			// Initialize the view to a rectangle located at (100, 100) and with a size of 400x200
			view.reset(sf::FloatRect(0 + x_offset, y_offset, 1024, 768));
			//view.rotate(x_offset);
			w->setView(view);
			r->render(w);		

			if(!r->getKillPlayer()){


				act.render(w);
			}
			if(deathRoom){

				w->draw(redSprite);

			}
			if(screamSound.getStatus() == sf::SoundSource::Playing){
				fadeSprite.setColor(sf::Color(255,128,128,255));
				w->draw(fadeSprite);
			}


			w->draw(shipSides);

			if(!fading)
			{
				explosion->render(w);
			}

			
		}
		else
		{
			r->render(w);

			if(!r->getKillPlayer()){
				act.render(w);
			}
			if(deathRoom){

				w->draw(redSprite);

			}
			if(screamSound.getStatus() == sf::SoundSource::Playing){
				fadeSprite.setColor(sf::Color(255,255,255,255));
				w->draw(fadeSprite);
			}
			w->draw(shipSides);

			if(!fading)
			{
				explosion->render(w);
			}

			x_offset = 10;

		}

		w->setView(w->getDefaultView());

		r->renderCodeBox(w);

		if(fading)
		{
			w->draw(fadeSprite);
		}


		for(int i = 0; i < 128; ++i)
		{
			//w->draw(starSpritesLayer1[i]);
			w->draw(starSpritesLayer2[i]);
			w->draw(starSpritesLayer3[i]);
		}

		PDALightSprite.setPosition(*r->getPDALightPos());
		w->draw(PDALightSprite);
		

	}else{
		//intro
		w->draw(introBackSprite);
		w->draw(introFrontSprite);
		for(int i = 0; i < 128; ++i)
		{
			w->draw(starSpritesLayer1[i]);
			w->draw(starSpritesLayer2[i]);
			w->draw(starSpritesLayer3[i]);
		}
		w->draw(introTitleSprite);
	}

	// Display window contents on screen
	r->getBadGuy()->render(w);

	if(explanationOpen)
	{
		w->draw(introBackSprite);

		for(int i = 0; i < 128; ++i)
		{
			w->draw(starSpritesLayer1[i]);
			w->draw(starSpritesLayer2[i]);
			w->draw(starSpritesLayer3[i]);
		}

		w->draw(explanationSprite);
		w->draw(heartSprite);
	}

	w->draw(scoreText);
}

Game::~Game(void)
{
}

void Game::fadeIn()
{
	if(fadeSprite.getColor().a > 9)
	{
		fadeSprite.setColor(sf::Color(255, 255, 255, (fadeSprite.getColor().a - 8)));
	}
	else
	{
		fadeInComplete = true;
	}
}

void Game::fadeOut()
{
	if(fadeSprite.getColor().a < 246)
	{
		fading = true;
		fadeSprite.setColor(sf::Color(255, 255, 255, (fadeSprite.getColor().a + 8)));
	}
	else
	{
		fadeOutComplete = true;
	}
}

void Game::finalFade()
{
	if(!scoreCalculated)
	{
		scoreCalculated = true;
		std::stringstream out;
		out << score;

		scoreString.insert(scoreString.getSize(), out.str());
		scoreText.setString(scoreString);

		scoreText.setPosition(512 - (scoreText.getGlobalBounds().width / 2), 384 - (scoreText.getGlobalBounds().height / 2));
	}

	static int i = 0;
	if(fadeSprite.getColor().a < 255)
	{
		fading = true;
		if( i == 2)
		{
			fadeSprite.setColor(sf::Color(255, 255, 255, (fadeSprite.getColor().a + 1)));
			i = 0;

			if(scoreText.getColor().a >= 254)
			{
				fadedIn = true;
			}

			if(fadedIn)
			{
				scoreText.setColor(sf::Color(255, 255, 255, (scoreText.getColor().a - 2)));
			}
			else
			{
				scoreText.setColor(sf::Color(255, 255, 255, (scoreText.getColor().a + 2)));
			}
		}
		else
		{
			i++;
		}
	}
	else
	{
		if( i == 120)
		{
			///// Reset Game
			scoreText.setColor(sf::Color(255, 255, 255, 0));
			i = 0;
			delete explosion;
			init();
			act.resetPosition();
			act.switchLightsOn();
		}
		else
		{
			i++;
			scoreText.setColor(sf::Color(255, 255, 255, 0));
		}

		// reset fadeOutComplete = true;
	}
}